import DisplayObject = egret.DisplayObject;

interface Size {
    width: number,
    height: number,
}

interface GridInfo extends Size {
    index: number,
    x: number,
    y: number,
}


const GLOBAL_SIZE: Size = {width: 640, height: 1136}


function getRandomColor() {
    return Math.floor(Math.random() * 0xffffff)
}

class MyGrid extends egret.Shape {
    public static STATUS_NORMAL = 0
    public static STATUS_RIGHT = 1
    public static STATUS_WRONG = 2
    public readonly info: GridInfo;
    public status: number = MyGrid.STATUS_NORMAL // 0 未打开，1 打开正确，2 打开错误

    public constructor(info: GridInfo) {
        super();
        this.info = info;
        this.drawGrid();
    }

    private drawGrid() {
        let colorA = getRandomColor();
        let colorB = getRandomColor();

        this.graphics.clear()

        this.graphics.beginFill(colorA);
        const {
            width: size,
            x, y
        } = this.info

        const halfSize = size / 2;
        this.graphics.drawRect(0, 0, halfSize, halfSize);
        this.graphics.endFill();
        this.graphics.beginFill(colorA);
        this.graphics.drawRect(halfSize, halfSize, halfSize, halfSize);
        this.graphics.endFill();
        this.graphics.beginFill(colorB);
        this.graphics.drawRect(halfSize, 0, halfSize, halfSize);
        this.graphics.endFill();
        this.graphics.beginFill(colorB);
        this.graphics.drawRect(0, halfSize, halfSize, halfSize);
        this.graphics.endFill();

        this.x = x
        this.y = y
    }
}


class Bg extends egret.Sprite {
    private readonly size: Size

    public constructor(size: Size) {
        super()
        this.size = size
        this.drawBg()
    }

    private drawBg() {
        // this.graphics.beginFill(getRandomColor())
        this.graphics.beginFill(0xffffff)
        this.graphics.drawRect(0, 0, this.size.width, this.size.height)
        this.graphics.endFill()
        this.x = 0
        this.y = 0
    }
}


function shuffle(array) {
    let currentIndex = array.length, temporaryValue, randomIndex;

    // While there remain elements to shuffle...
    while (0 !== currentIndex) {

        // Pick a remaining element...
        randomIndex = Math.floor(Math.random() * currentIndex);
        currentIndex -= 1;

        // And swap it with the current element.
        temporaryValue = array[currentIndex];
        array[currentIndex] = array[randomIndex];
        array[randomIndex] = temporaryValue;
    }

    return array;
}

function sleep(time) {
    return new Promise(resolve => setTimeout(resolve, time))
}

class ReactContainer extends egret.DisplayObjectContainer {
    private childMap: any = {}
    private keyCount = 0

    createChild([ItemConstructor, ...parameters]: any[], key = ItemConstructor + this.keyCount++) {
        let child = this.childMap[key]
        if (!child) {
            console.log('createChild')
            child = new ItemConstructor(...parameters)
            child.key = key
        } else {
            console.log('createChild cache')
        }
        return child
    }

    addChild(child) {
        if (child.key == null) {
            console.log('addChild')
            super.addChild(child)
        } else {
            if (!this.childMap[child.key]) {
                super.addChild(child)
                this.childMap[child.key] = child
            } else {
                console.log('addChild cache');
            }
        }

        return child
    }

    drawItems() {
        console.log(this.childMap)
        this.keyCount = 0
    }

}

class Demo1 extends ReactContainer {
    public static STATUS_SCAN: number = 0;
    public static STATUS_ANSWER: number = 1;
    public static STATUS_ANSWERED_RIGHT: number = 2;
    public static STATUS_ANSWERED_WRONG: number = 3;

    private readonly itemLength: number
    private readonly colNums: number
    private readonly gapPercent: number
    private targetHistory: number[] = []
    private targetIndex: number;
    private status: number = 0;     // 0 查看速记，1 猜选
    private resGroupIcons: Array<RES.ResourceItem>;


    constructor() {
        super()
        window.demo1 = this
        this.itemLength = 9
        this.colNums = 3
        this.gapPercent = .05
    }

    genTargetIndex() {
        let index: number = -1
        if (this.itemLength - this.targetHistory.length > 0) {
            let targetIndexRelative = Math.floor(Math.random() * (this.itemLength - this.targetHistory.length));
            let count = 0
            for (let i = 0; i < this.itemLength; i++) {
                if (this.targetHistory.indexOf(i) == -1) {
                    if (count === targetIndexRelative) {
                        index = i
                        break
                    }
                    count++;
                }
            }
        }
        return index
    }

    nextTarget() {
        const targetIndex = this.genTargetIndex()
        if (targetIndex === -1) {
            console.log('游戏结束')
            return
        }

        this.targetIndex = targetIndex;
        this.targetHistory.push(this.targetIndex)
    }

    async loadRes() {
        try {
            await RES.loadConfig("default.res.json", "resource/");
            await RES.loadGroup("icons");
        } catch (e) {
            console.error(e)
        }
        this.resGroupIcons = shuffle(RES.getGroupByName('icons'));
    }


    drawItems() {
        super.drawItems()
        const bg: Bg = this.createChild([Bg, GLOBAL_SIZE]);
        this.addChild(bg);
        const arr: any[] = Array.apply(null, new Array(this.itemLength))

        // const size = 148
        const size = GLOBAL_SIZE.width / ((this.colNums + 1) * this.gapPercent + this.colNums)
        const gap = size * this.gapPercent
        const grids = arr.map((val, idx) => {
            const colIndex = idx % this.colNums
            const rowIndex = Math.floor(idx / this.colNums)
            const x = size * colIndex + gap * (colIndex + 1)
            const y = size * rowIndex + gap * (rowIndex + 1)
            console.log([x, y, colIndex, rowIndex, idx, this.colNums].join('\t'))

            const gridInfo: GridInfo = {
                width: size,
                height: size,
                x,
                y,
                index: idx,
            }
            const grid: MyGrid = this.createChild([MyGrid, gridInfo])
            grid.touchEnabled = true;
            const statusAlphaMap = {
                [Demo1.STATUS_SCAN]: 0,
                [Demo1.STATUS_ANSWER]: 1,
                [Demo1.STATUS_ANSWERED_RIGHT]: 0,
                [Demo1.STATUS_ANSWERED_WRONG]: 0,
            }
            grid.alpha = [MyGrid.STATUS_RIGHT, MyGrid.STATUS_WRONG].indexOf(grid.status) !== -1 ? 0 : statusAlphaMap[this.status]

            if ([
                Demo1.STATUS_ANSWER
            ].indexOf(this.status) !== -1) {
                grid.addEventListener(egret.TouchEvent.TOUCH_TAP, async () => {
                    grid.alpha = 0
                    const targetGrid = grids.filter((g: MyGrid) => g.info.index === this.targetIndex)[0]
                    if (idx === this.targetIndex) {
                        console.log('恭喜')
                        targetGrid.status = MyGrid.STATUS_RIGHT
                        await this.changeStatus(Demo1.STATUS_ANSWERED_RIGHT)
                        await sleep(3000)
                        await this.changeStatus(Demo1.STATUS_SCAN)
                        await this.changeStatus(Demo1.STATUS_ANSWER)
                    } else {
                        console.log('失败')
                        targetGrid.status = MyGrid.STATUS_WRONG
                        await this.changeStatus(Demo1.STATUS_ANSWERED_WRONG)
                        await sleep(3000)
                        await this.changeStatus(Demo1.STATUS_SCAN)
                        await this.changeStatus(Demo1.STATUS_ANSWER)
                    }
                }, this);
            }

            const img = this.createChild([egret.Bitmap]);
            img.width = size
            img.height = size
            img.fillMode = egret.BitmapFillMode.SCALE
            img.texture = RES.getRes(this.resGroupIcons[idx % this.resGroupIcons.length].name)
            img.x = x
            img.y = y
            this.addChild(img)

            this.addChild(grid);

            if (idx === arr.length - 1 && [
                Demo1.STATUS_ANSWER,
                Demo1.STATUS_ANSWERED_WRONG,
                Demo1.STATUS_ANSWERED_RIGHT,
            ].indexOf(this.status) !== -1) {
                const img = this.createChild([egret.Bitmap])
                img.width = size
                img.height = size
                img.fillMode = egret.BitmapFillMode.SCALE
                img.texture = RES.getRes(this.resGroupIcons[this.targetIndex].name)
                img.x = (GLOBAL_SIZE.width - size) / 2
                img.y = y + size + gap
                this.addChild(img)
            }

            return grid
        })
    }

    async changeStatus(status) {
        this.status = status
        switch (status) {
            case Demo1.STATUS_SCAN:
                this.nextTarget()
                break
            case Demo1.STATUS_ANSWER:
                break
        }
        this.drawItems()
    }

    async $onAddToStage(stage: egret.Stage, nestLevel: number) {
        await this.loadRes();
        await this.changeStatus(Demo1.STATUS_SCAN)
        await sleep(2 * 1000)
        await this.changeStatus(Demo1.STATUS_ANSWER)
    }

}
